<?php

namespace App\Http\Utils\Promotion;


use App\Http\Utils\Integral\Time;
use Illuminate\Support\Facades\DB;

class Order
{
    const HAS_NOT_JOIN_RELATION = "该商户下没有推广你的推广关系";

    /**
     * 商户
     * @var string
     */
    public $shopId;

    /**
     * 用户
     * @var string
     */
    public $userId;

    /**
     * 订单号
     * @var string
     */
    public $orderNum;

    /**
     * 总金额
     * @var int
     */
    public $total;

    /**
     * Order constructor.
     * @param string $shopId 商户ID
     * @param string $userId 用户ID
     * @param string $orderNum 订单号
     * @param int $total 消费总金额
     */
    public function __construct($shopId, $userId, $orderNum, $total)
    {
        $this->shopId = $shopId;
        $this->userId = $userId;
        $this->orderNum = $orderNum;
        $this->total = $total;
    }

    /**
     *
     */
    private function record()
    {
        DB::table('promotion_order')->insert([
            'shop_id'     => $this->shopId,
            'user_id'     => $this->userId,
            'order_num'   => $this->orderNum,
            'total'       => $this->total,
            'create_time' => Time::current(),
            'update_time' => Time::current(),
        ]);
    }

    /**
     * @param $userId
     * @return \Illuminate\Database\Eloquent\Model|null|static
     */
    private function parent($userId)
    {
        return DB::table('promotion_relation')
            ->where([
                'promotion_relation.user_id' => $userId,
                'promotion_relation.shop_id' => $this->shopId,
            ])->value('promotion_relation.parent_user_id');
    }

    /**
     * @param $userId
     * @param $planId
     * @return \Illuminate\Database\Eloquent\Model|null|static
     */
    private function joinPlan($userId, $planId)
    {
        if ($userId === "0") {
            return null;
        }
        return DB::table('promotion_join_plan')
            ->where([
                'promotion_join_plan.user_id' => $userId,
                'promotion_join_plan.shop_id' => $this->shopId,
                'promotion_join_plan.plan_id' => $planId,
                'promotion_join_plan.exit'    => 'false',
            ])->lockForUpdate()
            ->first();
    }

    public function account()
    {
        DB::beginTransaction();
        try {
            $plan = DB::table('promotion_relation')
                ->leftJoin('promotion_plan', function ($join) {
                    $join->on('promotion_plan.id', '=', 'promotion_relation.plan_id');
                })->where([
                    'promotion_relation.user_id' => $this->userId,
                    'promotion_relation.shop_id' => $this->shopId,
                ])->first([
                    'promotion_relation.parent_user_id',
                    'promotion_plan.id as plan_id',
                    'promotion_plan.name',
                    'promotion_plan.one',
                    'promotion_plan.two',
                ]);
            if (is_null($plan)) {
                throw new \Exception(self::HAS_NOT_JOIN_RELATION, 202);
            }
            $grant = [];
            $one = $plan->parent_user_id;
            if ($one !== "0") {
                if ($join1 = $this->joinPlan($one, $plan->plan_id)) {
                    $oneUser = new User($one, $this->shopId);
                    $oneAmount = $this->total * $plan->one / 100;
                    $oneUser->flow($this->orderNum, json_encode([
                        'ratio' => $plan->one,
                        'level' => 1,
                    ]), $oneAmount, $plan->plan_id);
                    $oneUser->userRecord();
                    DB::table('promotion_join_plan')
                        ->where('id', $join1->id)
                        ->update([
                            'commission'  => $join1->commission + $oneAmount,
                            'withdrawals' => $join1->withdrawals + $oneAmount,
                            'update_time' => Time::current(),
                        ]);
                    $grant['one'] = $oneAmount;
                }
                if ($two = $this->parent($one)) {
                    if ($join2 = $this->joinPlan($two, $plan->plan_id)) {
                        $twoUser = new User($two, $this->shopId);
                        $twoAmount = $this->total * $plan->two / 100;
                        $twoUser->flow($this->orderNum, json_encode([
                            'ratio' => $plan->two,
                            'level' => 2,
                        ]), $twoAmount, $plan->plan_id);
                        $twoUser->userRecord();
                        DB::table('promotion_join_plan')
                            ->where('id', $join2->id)
                            ->update([
                                'commission'  => $join2->commission + $twoAmount,
                                'withdrawals' => $join2->withdrawals + $twoAmount,
                                'update_time' => Time::current(),
                            ]);
                        $grant['two'] = $twoAmount;
                    }
                }
            }
            $this->record();
            DB::commit();
            return $grant;
        } catch (\Throwable $throwable) {
            DB::rollBack();
            throw $throwable;
        }
    }
}